package heap;

import global.AttrType;
import global.PageId;

import java.io.IOException;

public class BasicPattern extends Tuple {

	private short numFlds = 13;
	private short [] strSizes = null;
	private AttrType [] types = {new AttrType (AttrType.attrInteger),
		new AttrType (AttrType.attrInteger),
		new AttrType (AttrType.attrInteger),
		new AttrType (AttrType.attrInteger),
		new AttrType (AttrType.attrInteger),
		new AttrType (AttrType.attrInteger),
		new AttrType (AttrType.attrInteger),
		new AttrType (AttrType.attrInteger),
		new AttrType (AttrType.attrInteger),
		new AttrType (AttrType.attrInteger),
		new AttrType (AttrType.attrInteger),
		new AttrType (AttrType.attrInteger),
		new AttrType (AttrType.attrReal)};

	int numOfNodes;
	
	private void init(short numFlds, int numOfNodes, AttrType[] types){
		this.types = types;
		this.numFlds = numFlds;
		this.numOfNodes = numOfNodes;
	}

	public BasicPattern(int numNodes) throws InvalidTypeException, InvalidTupleSizeException, IOException{
		super(164);
		short fields = (short) (numNodes*2 + 1);
		AttrType[] type = new AttrType[fields];
		int i = 0;
		for (; i < fields -1 ; i++) {
			type[i] = new AttrType(AttrType.attrInteger);
		}
		type[i] = new AttrType(AttrType.attrReal);
		this.types = type;
		this.numFlds = fields;
		this.numOfNodes = numNodes;
		this.setHdr(numFlds, types, strSizes);

	}
	
	public BasicPattern(int numNodes,short numFlds, AttrType[] types) throws InvalidTypeException, InvalidTupleSizeException, IOException{
		super(46);
		this.setHdr(numFlds, types, strSizes);

		init(numFlds, numNodes, types);
	}

	public BasicPattern(NodeID id1, NodeID id2) throws InvalidTypeException, InvalidTupleSizeException, IOException, FieldNumberOutOfBoundException{
	    super(46);
	    this.numOfNodes = 2;
		this.numFlds = 4;
		AttrType[] type = new AttrType[numFlds];
		int i = 0;
		for (; i < numFlds ; i++) {
			type[i] = new AttrType(AttrType.attrInteger);
		}
		this.types= type;
		
		this.setHdr(numFlds, types, strSizes);
		
		this.setIntFld (1, id1.pageNo.pid);
		this.setIntFld (2, id1.slotNo);
		this.setIntFld (3, id2.pageNo.pid);
		this.setIntFld (4, id2.slotNo);
	}

	public BasicPattern(NodeID id1, NodeID id2, float confidence) throws InvalidTypeException, InvalidTupleSizeException, IOException, FieldNumberOutOfBoundException{
	    super(46);
	    this.numOfNodes = 2;
		this.numFlds = 5;
		AttrType[] type = new AttrType[numFlds];
		int i = 0;
		for (; i < numFlds -1 ; i++) {
			type[i] = new AttrType(AttrType.attrInteger);
		}
		type[i] = new AttrType(AttrType.attrReal);
		this.types= type;
		
		this.setHdr(numFlds, types, strSizes);
		this.setIntFld (1, id1.pageNo.pid);
		this.setIntFld (2, id1.slotNo);
		this.setIntFld (3, id2.pageNo.pid);
		this.setIntFld (4, id2.slotNo);
		this.setFloFld (5, confidence);
	}

	public BasicPattern(NodeID id1, NodeID id2, NodeID id3, NodeID id4) throws InvalidTypeException, InvalidTupleSizeException, IOException, FieldNumberOutOfBoundException{
	    super(82);
	    this.numOfNodes = 4;
		this.numFlds = 8;
		AttrType[] type = new AttrType[numFlds];
		int i = 0;
		for (; i < numFlds ; i++) {
			type[i] = new AttrType(AttrType.attrInteger);
		}
		this.types= type;
		
		this.setHdr(numFlds, types, strSizes);
		this.setIntFld (1, id1.pageNo.pid);
		this.setIntFld (2, id1.slotNo);
		this.setIntFld (3, id2.pageNo.pid);
		this.setIntFld (4, id2.slotNo);
		this.setIntFld (5, id3.pageNo.pid);
		this.setIntFld (6, id3.slotNo);
		this.setIntFld (7, id4.pageNo.pid);
		this.setIntFld (8, id4.slotNo);
	}

	public BasicPattern(NodeID id1, NodeID id2, NodeID id3, NodeID id4, float confidence) throws InvalidTypeException, InvalidTupleSizeException, IOException, FieldNumberOutOfBoundException{
	    super(82);
	    this.numOfNodes = 4;
		this.numFlds = 9;
		AttrType[] type = new AttrType[numFlds];
		int i = 0;
		for (; i < numFlds -1 ; i++) {
			type[i] = new AttrType(AttrType.attrInteger);
		}
		type[i] = new AttrType(AttrType.attrReal);
		this.types= type;
		//System.out.println(numOfNodes + "," + numFlds + "," + types);
		this.setHdr(numFlds, types, strSizes);
		this.setIntFld (1, id1.pageNo.pid);
		this.setIntFld (2, id1.slotNo);
		this.setIntFld (3, id2.pageNo.pid);
		this.setIntFld (4, id2.slotNo);
		this.setIntFld (5, id3.pageNo.pid);
		this.setIntFld (6, id3.slotNo);
		this.setIntFld (7, id4.pageNo.pid);
		this.setIntFld (8, id4.slotNo);
		this.setFloFld (9, confidence);
	}

	public BasicPattern(NodeID id1, NodeID id2, NodeID id3, NodeID id4, NodeID id5, NodeID id6) throws InvalidTypeException, InvalidTupleSizeException, IOException, FieldNumberOutOfBoundException{
	    super(82);
	    this.numOfNodes = 6;
		this.numFlds = 12;
		AttrType[] type = new AttrType[numFlds];
		int i = 0;
		for (; i < numFlds ; i++) {
			type[i] = new AttrType(AttrType.attrInteger);
		}
		this.types= type;
		this.setHdr(numFlds, types, strSizes);
		this.setIntFld (1, id1.pageNo.pid);
		this.setIntFld (2, id1.slotNo);
		this.setIntFld (3, id2.pageNo.pid);
		this.setIntFld (4, id2.slotNo);
		this.setIntFld (5, id3.pageNo.pid);
		this.setIntFld (6, id3.slotNo);
		this.setIntFld (7, id4.pageNo.pid);
		this.setIntFld (8, id4.slotNo);
		this.setIntFld (9, id3.pageNo.pid);
		this.setIntFld (10, id3.slotNo);
		this.setIntFld (11, id4.pageNo.pid);
		this.setIntFld (12, id4.slotNo);
	}

	public BasicPattern(NodeID id1, NodeID id2, NodeID id3, NodeID id4, NodeID id5, NodeID id6, float confidence) throws InvalidTypeException, InvalidTupleSizeException, IOException, FieldNumberOutOfBoundException{
	    super(82);
	    this.numOfNodes = 6;
		this.numFlds = 13;
		AttrType[] type = new AttrType[numFlds];
		int i = 0;
		for (; i < numFlds -1 ; i++) {
			type[i] = new AttrType(AttrType.attrInteger);
		}
		type[i] = new AttrType(AttrType.attrReal);
		this.types= type;
		this.setHdr(numFlds, types, strSizes);
		this.setIntFld (1, id1.pageNo.pid);
		this.setIntFld (2, id1.slotNo);
		this.setIntFld (3, id2.pageNo.pid);
		this.setIntFld (4, id2.slotNo);
		this.setIntFld (5, id3.pageNo.pid);
		this.setIntFld (6, id3.slotNo);
		this.setIntFld (7, id4.pageNo.pid);
		this.setIntFld (8, id4.slotNo);
		this.setIntFld (9, id3.pageNo.pid);
		this.setIntFld (10, id3.slotNo);
		this.setIntFld (11, id4.pageNo.pid);
		this.setIntFld (12, id4.slotNo);
		this.setFloFld (13, confidence);
	}

	public NodeID getNode(int nodeNum) throws Exception{
		if(nodeNum < numOfNodes && nodeNum > -1){
			switch(nodeNum){
			case 1: return (new NodeID (new PageId(this.getIntFld(1)), this.getIntFld(2)));
			case 2: return (new NodeID (new PageId(this.getIntFld(3)), this.getIntFld(4)));
			case 3: return (new NodeID (new PageId(this.getIntFld(5)), this.getIntFld(6)));
			case 4: return (new NodeID (new PageId(this.getIntFld(7)), this.getIntFld(8)));
			case 5: return (new NodeID (new PageId(this.getIntFld(9)), this.getIntFld(10)));
			case 6: return (new NodeID (new PageId(this.getIntFld(11)), this.getIntFld(12)));
			default: throw new Exception("verify index..");
			}
		}else{
			throw new Exception("INVALID INDEX FOR NODE SELECTION.");
		}
	}
	
	public float getConfidence() throws FieldNumberOutOfBoundException, IOException{
		return this.getFloFld(numFlds);
	}
	
	
	public void setConfidence (float confidence) throws FieldNumberOutOfBoundException, IOException {
		this.setFloFld (numFlds, confidence);		
	}
	
	public void printBP() throws FieldNumberOutOfBoundException, IOException{
		StringBuffer buf = new StringBuffer();
		int i =1;
		for(i =1; i< numFlds; i++){
			buf.append(this.getIntFld(i) + ",");
		}
		buf.append(this.getFloFld(numFlds));
		System.out.println("i="+i+" , BP = "+buf);
	}
}
